/**************************************************************************** 
 * Meta，一个轻量级的静态分区Hypervisor 
 *
 * 版权(c) , 2022-
 *
 * 作者:
 *      Tupelo Shen <shenwanjiang2013@163.com>
 *
 * Meta是一个自由软件，你可以在遵循GNU GPLv2协议的条件下，重新修改并发布它。
 *
 ***************************************************************************/

#include <cpu.h>
#include <interrupts.h>

#include <platform.h>

#include <arch/gic.h>
#include <mem.h>
#include <arch/sysregs.h>
#include <vm.h>

#ifndef GIC_VERSION
#error "GIC_VERSION not defined for this platform"
#endif

/****************************************************************************
 ****                           公共函数定义                             ****
 ****************************************************************************/
/**
 * 功能描述: 初始化GIC通用中断控制器，并使能维护中断
 * 入口参数: void
 * 出口参数: void
 * 返 回 值: void
 * 修改日期: 2022-09-21
 */
void interrupts_arch_init(void)
{
    gic_init();
    interrupts_cpu_enable(platform.arch.gic.maintenance_id, true);
}

/**
 * 功能描述: 获取中断pending状态
 * 入口参数: int_id:    中断ID
 * 出口参数: void
 * 返 回 值: bool,      挂起返回1，失败返回0
 * 修改日期: 2022-09-21
 */
bool interrupts_arch_check(irqid_t int_id)
{
    return gic_get_pend(int_id);
}

/**
 * 功能描述: 清除中断pending、active状态
 * 入口参数: int_id:    中断ID
 * 出口参数: void
 * 返 回 值: void
 * 修改日期: 2022-09-21
 */
void interrupts_arch_clear(irqid_t int_id)
{
    gic_set_act(int_id, false);
    gic_set_pend(int_id, false);
}

/**
 * 功能描述: 使能某个中断（与架构相关）
 * 入口参数: int_id:    中断ID
 *           en:        使能位
 * 出口参数: void
 * 返 回 值: void
 * 修改日期: 2022-09-21
 */
void interrupts_arch_enable(irqid_t int_id, bool en)
{
    gic_set_enable(int_id, en);
    gic_set_prio(int_id, 0x01);
    if (GIC_VERSION == GICV2) {
        // TODO: GICv2暂时不支持
        // gicd_set_trgt(int_id, 1 << cpu.id);
    } else {
        gicd_set_route(int_id, cpu.arch.mpidr);
    }
}

/**
 * 功能描述: 使能某个中断（与架构相关）
 * 入口参数: target_cpu,目标核
 *           ipi_id,    核间中断号
 * 出口参数: void
 * 返 回 值: void
 * 修改日期: 2022-09-21
 */
void interrupts_arch_ipi_send(cpuid_t target_cpu, irqid_t ipi_id)
{
    if (ipi_id < GIC_MAX_SGIS) gic_send_sgi(target_cpu, ipi_id);
}

/**
 * 功能描述: 将中断注入到VM中（与架构相关）
 * 入口参数: vm,    目标VM
 *           id,    中断号
 * 出口参数: void
 * 返 回 值: void
 * 修改日期: 2022-09-21
 */
void interrupts_arch_vm_inject(struct vm *vm, irqid_t id)
{
    vgic_inject(&vm->arch.vgicd, id, cpu.vcpu->id);
}

/**
 * 功能描述: 判断中断是否冲突
 * 入口参数: interrupt_bitmap,  中断位图，每一位表示一个中断
 *           int_id,            中断号
 * 出口参数: void
 * 返 回 值: bool,     冲突返回1，否则返回0
 * 修改日期: 2022-09-21
 */
inline bool interrupts_arch_conflict(bitmap_t* interrupt_bitmap, irqid_t int_id)
{
    return (bitmap_get(interrupt_bitmap, int_id) && int_id > GIC_CPU_PRIV);
}

/**
 * 功能描述: VM绑定虚拟中断
 * 入口参数: vm,    目标VM
 *           id,    中断号
 * 出口参数: void
 * 返 回 值: void
 * 修改日期: 2022-09-21
 */
void interrupts_arch_vm_assign(struct vm *vm, irqid_t id)
{
    vgic_set_hw(vm, id);
}